#include "GameMiner.h"
#include "..\Engine\Base\Base.h"
#include "..\Engine\Graphics\Background.h"
#include "..\Engine\Graphics\SpriteManager.h"
#include "..\Engine\Logic\Object2DManager.h"
#include "..\Engine\Logic\Timer.h"
#include "..\Engine\GUI\GUIManager.h"
#include "..\Engine\GUI\GUIText.h"
#include "..\Engine\Sound\SoundManager.h"
#include "..\Engine\Particles\ParticleManager.h"
#include "Board.h"
#include "SDL.h"
#include <fstream>

CGameMiner::CGameMiner()
	: m_bfpsLimited(true)
	, m_eGameState(GS_WAITING_TO_START)
{

}

void CGameMiner::Init()
{
	//Init Core
	m_pCore->Init("GameMiner");

	//Init timers
	m_pfpsCounter = new CTimer();
	m_pfpsCounter->Start();
	m_pGameTime = new CTimer();
	m_pFinishedCounter = new CTimer();

	//load high score
	std::ifstream load( "game_data" );
	if (load != NULL)
	{
		load >> m_HighScore;
		load.close();
	}
	else m_HighScore = 1000;
	
	//Load Graphics
	SDL_Renderer* l_pRenderer = m_pCore->GetRenderer();	
	m_pCore->GetSpriteManager()->LoadSprite("Blue.png", l_pRenderer);
	m_pCore->GetSpriteManager()->LoadSprite("Green.png", l_pRenderer);
	m_pCore->GetSpriteManager()->LoadSprite("Purple.png", l_pRenderer);
	m_pCore->GetSpriteManager()->LoadSprite("Red.png", l_pRenderer);
	m_pCore->GetSpriteManager()->LoadSprite("Yellow.png", l_pRenderer);
	m_pCore->GetSpriteManager()->LoadSprite("sBlue.png", l_pRenderer);
	m_pCore->GetSpriteManager()->LoadSprite("sGreen.png", l_pRenderer);
	m_pCore->GetSpriteManager()->LoadSprite("sPurple.png", l_pRenderer);
	m_pCore->GetSpriteManager()->LoadSprite("sRed.png", l_pRenderer);
	m_pCore->GetSpriteManager()->LoadSprite("sYellow.png", l_pRenderer);
	m_pCore->GetSpriteManager()->SetColor(128,128,128);
	m_pCore->GetBackground()->SetColor(128,128,128);

	//Load Sounds
	m_pCore->GetSoundManager()->LoadSound("explosion.wav");
	m_pCore->GetSoundManager()->LoadSound("hit.wav");
	m_pCore->GetSoundManager()->LoadSound("switch.wav");
	m_pCore->GetSoundManager()->LoadSound("public.wav");

	//Init Board
	m_pBoard = new CBoard(8,8);
	m_pBoard->Init(280, 75, 280, 280 );		

	//Init GUI
	m_pCore->GetGUIManager()->AddTextBox("fps", "FPS: 0", 20, 20);
	m_pCore->GetGUIManager()->getResource("fps")->SetVisible(false);
	m_pGUITime = (CGUIText*) m_pCore->GetGUIManager()->AddTextBox("time", "Time:  1:00", 20, 100);	
	m_pGUITime->SetBold(true);
	m_pGUITime->SetFontSize(24);
	m_pGUITime->SetVisible(false);
	m_pGUIScore =  (CGUIText*) m_pCore->GetGUIManager()->AddTextBox("score", "Score: ", 20, 140);	 
	m_pGUIScore->SetBold(true);
	m_pGUIScore->SetFontSize(24);
	m_pGUIScore->SetVisible(false);
	m_pGUIStartInfo = (CGUIText*) m_pCore->GetGUIManager()->AddTextBox("start", "(Click to Start)", 220, 200);
	m_pGUIStartInfo->SetBold(true);
	m_pGUIStartInfo->SetFontSize(24);				
	m_pGUIEndScore = (CGUIText*) m_pCore->GetGUIManager()->AddTextBox("endScore", "Score: 0", 150, 140);
	m_pGUIEndScore->SetBold(true);
	m_pGUIEndScore->SetFontSize(48);				
	m_pGUIEndScore->SetVisible(false);
	m_pGUIHighScore = (CGUIText*) m_pCore->GetGUIManager()->AddTextBox("highscore", "High Score: "+std::to_string(_Longlong(m_HighScore)), 280, 2);	 
	m_pGUIHighScore->SetBold(true);
	m_pGUIHighScore->SetFontSize(12);
	m_pGUIHighScore->SetVisible(false);
}

void CGameMiner::Start()
{	
	m_eGameState = GS_RUNNING;
	m_pGUITime->SetVisible(true);
	m_pGUIScore->SetVisible(true);
	m_pGUIHighScore->SetVisible(true);
	m_pGameTime->Start();
	m_pBoard->Start();
	m_pCore->GetSpriteManager()->SetColor(255,255,255);
	m_pCore->GetBackground()->SetColor(255,255,255);
}

void CGameMiner::Stop()
{
	m_eGameState = GS_FINISHED;
	m_pGameTime->Stop();
	m_pBoard->Stop();
	m_pGUITime->SetVisible(false);
	m_pGUIScore->SetVisible(false);
	m_pGUIHighScore->SetVisible(false);
	m_pCore->GetSpriteManager()->SetColor(128,128,128);
	m_pCore->GetBackground()->SetColor(128,128,128);	
}

void CGameMiner::ManageEvent(const SDL_Event* e)
{
	if (e->type == SDL_KEYUP)
	{
		if (e->key.keysym.sym == SDLK_F1)
		{
			CGUIText* l_text = (CGUIText*)m_pCore->GetGUIManager()->getResource("fps");
			l_text->SetVisible(!l_text->IsVisible());
		}
	}
	else if(e->type == SDL_MOUSEBUTTONDOWN)
	{
		if (e->button.button == SDL_BUTTON_LEFT)
		{			
			if (m_eGameState == GS_RUNNING)
			{
				m_pBoard->SelectGem(e->button.x, e->button.y);
			
			}
			else if (m_eGameState == GS_FINISHED)
			{
				if (m_pFinishedCounter->GetTimeCounter() / 1000 > FINISHED_TIME)
				{
					m_pFinishedCounter->Stop();
					m_eGameState = GS_WAITING_TO_START;
					m_pGUIStartInfo->SetVisible(true);
				}
			}
			else if (m_eGameState == GS_WAITING_TO_START)
			{
				m_pGUIStartInfo->SetVisible(false);
				m_pGUIEndScore->SetVisible(false);
				Start();
			}			
		}
	}
}

void CGameMiner::Update()
{
	m_pfpsCounter->Update();	
	float l_dt = (m_pfpsCounter->GetDeltaTick() / 1000.f);
	UpdateFPS();
	m_pGameTime->Update();
	m_pFinishedCounter->Update();

	m_pCore->GetObject2DManager()->Update(l_dt);
	m_pCore->GetParticleManager()->Update(l_dt);
	m_pCore->GetGUIManager()->Update(l_dt);
	m_pBoard->Update(l_dt);	
	m_pGUIScore->SetText("Score: "+std::to_string(_Longlong(m_pBoard->GetScore())));		
		
	//update time
	int32 l_secsToGo = (GAME_TIME - (m_pGameTime->GetTimeCounter() / 1000)) % 60;
	int32 l_minsToGo = (GAME_TIME - (m_pGameTime->GetTimeCounter() / 1000)) / 60;
	std::string l_sSecs;
	if ((9 >= l_secsToGo) && (l_secsToGo >= 0))
		l_sSecs = "0"+std::to_string(_Longlong(l_secsToGo));
	else
		l_sSecs = std::to_string(_Longlong(l_secsToGo));
	m_pGUITime->SetText("Time:  "+std::to_string(_Longlong(l_minsToGo))+":"+l_sSecs);

	//Game finished?
	if ((m_pGameTime->GetTimeCounter() / 1000) > GAME_TIME )
	{
		//end game
		int32 l_score = m_pBoard->GetScore();
		Stop();				
		if (l_score > m_HighScore)
		{
			m_HighScore = l_score;
			m_pGUIEndScore->SetText("New High Score!! "+std::to_string(_Longlong(l_score)));
			m_pGUIEndScore->SetX(20);
			m_pGUIHighScore->SetText("High Score: "+std::to_string(_Longlong(l_score)));
			//Open a file for writing
			std::ofstream save( "game_data" );       		
			save << m_HighScore;
			save.close();			
		}
		else
		{
			m_pGUIEndScore->SetText("SCORE: "+std::to_string(_Longlong(l_score)));
			m_pGUIEndScore->SetX(150);
		}
		m_pGUIEndScore->SetVisible(true);				
		m_pFinishedCounter->Start();				
		m_pCore->GetSoundManager()->PlaySound("public.wav");
	}

	if (m_eGameState == GS_FINISHED)
	{
		if (m_pFinishedCounter->GetTimeCounter() / 1000 > FINISHED_TIME)
		{
			m_pGUIStartInfo->SetVisible(true);
			m_pFinishedCounter->Stop();
			m_eGameState = GS_WAITING_TO_START;
		}
	}
}

void CGameMiner::UpdateFPS()
{
	if (m_pfpsCounter->GetTimeCounter() >= 1000) //every second
	{
		int32 l_fps = (int32)(1000.f / m_pfpsCounter->GetDeltaTick());
		std::string l_textFps = "FPS: "+std::to_string(_LONGLONG(l_fps));

		CGUIText* l_text = (CGUIText*)m_pCore->GetGUIManager()->getResource("fps");
		l_text->SetText(l_textFps);
		//reset fpscounter
		m_pfpsCounter->Stop();
		m_pfpsCounter->Start();
	}
}

void CGameMiner::Render()
{
	m_pCore->BeginRender();
	//**** BEGIN RENDER SCENE ***

	m_pCore->GetBackground()->Render();
	m_pCore->GetObject2DManager()->Render();
	m_pCore->GetParticleManager()->Render(m_pCore->GetRenderer());
	m_pCore->GetGUIManager()->Render();

	//**** END RENDER SCENE *****
	m_pCore->EndRender();

	//If we want to cap the frame rate
	if( (m_bfpsLimited) && (m_pfpsCounter->GetDeltaTick() < (1000 / MAX_FPS))  )
    {
        //Sleep the remaining frame time		
		SDL_Delay( (uint32)(( 1000 / MAX_FPS ) - m_pfpsCounter->GetDeltaTick()) );
    }
}
